﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;

namespace Streambolics.Hp41s.Gui
{
    /// <summary>
    ///     A control that shows an HP-41C front side without any
    ///     predefined markings on any key.
    /// </summary>

    public class BlankNut : EngineControl
    {
        private static readonly int [] _RowPixels = new int[] { 0, 0, 237, 286, 317, 368, 397, 445, 475, 525, 555, 610, 640, 696, 727, 780, 813, 867 };
        private static readonly int[] _FirstRow = new int[] { };
        private static readonly int[] _BigRow = new int[] { 46, 110, 133, 195, 216, 280, 303, 366, 389, 450 };
        private static readonly int[] _EnterRow = new int[] { 46, 195, 216, 280, 303, 366, 389, 450 };
        private static readonly int[] _DigitRow = new int[] { };

        /// <summary>
        ///     Create a new Blanknut control.
        /// </summary>

        public BlankNut ()
        {
            Width = 250;
            Height = 460;
        }

        protected override void OnPaint (PaintEventArgs e)
        {
            Rectangle r = DisplayRectangle;
            Bitmap b = Resources.BlankNut;

            if (b != null)
            {
                e.Graphics.DrawImage (b, r, 0, 0, b.Width, b.Height, GraphicsUnit.Pixel);
            }

            //  TODO : Render the keyboard here...
            RenderText (e.Graphics, r);
        }

        private bool FindKeyInRow (int x, out int col, int[] cols)
        {
            int c = 0;
            while (c < cols.Length)
            {
                if (x >= cols[c] && x <= cols[c + 1])
                {
                    col = c / 2 + 1;
                    return true;
                }
                c += 2;
            }
            col = -1;
            return false;
        }

        /// <summary>
        ///     Find the key at the given x,y position.
        /// </summary>
        /// <param name="x">
        /// </param>
        /// <param name="y">
        /// </param>
        /// <param name="row">
        /// </param>
        /// <param name="col">
        /// </param>
        /// <returns>
        ///     <c>True</c> if there is a key at x,y, in which case the
        ///     id of the key is in <c>row</c> and <c>col</c>.
        ///     <c>False</c> otherwise.
        /// </returns>

        public bool FindKey (int x, int y, out int row, out int col)
        {
            // 12 = 1/X
            // -53 = CF

            int r = 0;
            while (r < _RowPixels.Length)
            {
                if (y >= _RowPixels[r] && y <= _RowPixels[r + 1])
                {
                    break;
                }
                r += 2;
            }

            row = r / 2;

            switch (row)
            {
                case 0:
                    return FindKeyInRow (x, out col, _FirstRow);

                case 1:
                case 2:
                case 3:
                    return FindKeyInRow (x, out col, _BigRow);

                case 4:
                    return FindKeyInRow (x, out col, _EnterRow);

                case 5:
                case 6:
                case 7:
                case 8:
                    return FindKeyInRow (x, out col, _DigitRow);
            }
            col = -1;
            return false;
        }

        public bool FindKey (MouseEventArgs e, out int row, out int col)
        {
            int x = (e.X * 500) / Width;
            int y = (e.Y * 914) / Height;
            return FindKey (x, y, out row, out col);
        }

        protected override void OnMouseClick (MouseEventArgs e)
        {
            base.OnMouseClick (e);
            if (Machine != null)
            {
                int r, c;
                if (FindKey (e, out r, out c))
                {
                    Machine.KeyClick (r * 10 + c);
                }
            }
        }

        protected override void OnDragStart (Streambolics.Gui.DragStartEventArgs e)
        {
            base.OnDragStart (e);
            if (Machine != null)
            {
                e.DragObject = new DragData (Machine, this);
            }
        }

        protected override void OnDragEnter (DragEventArgs aDragData)
        {
            base.OnDragEnter (aDragData);
            Data d = GetDragData<Data> (aDragData);

            if (d != null)
            {
                aDragData.Effect = DragDropEffects.Copy;
            }
        }

        protected override void OnDragDrop (DragEventArgs aDragData)
        {
            base.OnDragDrop (aDragData);
            Data d = GetDragData<Data> (aDragData);

            if (d != null)
            {

                // TODO : execute the instruction.
                //Data = d;
            }
        }

    }
}
